package com.yuns.live.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.github.tobato.fastdfs.domain.StorePath;
import com.github.tobato.fastdfs.domain.ThumbImageConfig;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import com.yuns.course.vo.CourseVO;
import com.yuns.live.dto.LiveDto;
import com.yuns.live.entity.LiveBase;
import com.yuns.live.entity.LiveInfo;
import com.yuns.live.entity.LiveUserRel;
import com.yuns.live.entity.LiveVideoFile;
import com.yuns.live.mapper.LiveBaseMapper;
import com.yuns.live.mapper.LiveUserRelMapper;
import com.yuns.live.param.LiveParam;
import com.yuns.live.service.*;
import com.yuns.live.vo.LiveVO;
import com.yuns.live.vo.SpecifyPersonVO;
import com.yuns.util.CommonExcel;
import com.yuns.util.FileUtil;
import com.yuns.util.ResultJson;
import it.sauronsoftware.jave.Encoder;
import it.sauronsoftware.jave.MultimediaInfo;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.logging.SimpleFormatter;
import java.util.stream.Collectors;

@Service
public class LiveServiceImpl implements ILiveService {

    private static final Logger LOGGER = LoggerFactory.getLogger(LiveServiceImpl.class);

    private static final List<String> CONTENT_TYPES =
            Arrays.asList("avi", "mov", "rmvb", "rm", "flv", "mp4", "3gp", "AVI", "MOV", "RMVB", "RM", "FLV", "MP4", "3GP");

    private final String FILE_TYPE_V = "V";

    private final String FILE_TYPE_P = "P";

    @Resource
    private ILiveBaseService liveBaseService;

    @Resource
    private ILiveInfoService liveInfoService;

    @Resource
    private ILiveVideoFileService liveVideoFileService;

    @Autowired
    private FastFileStorageClient storageClient;

    @Autowired
    private ThumbImageConfig thumbImageConfig;

    @Resource
    private LiveBaseMapper liveBaseMapper;

    @Resource
    private LiveUserRelMapper liveUserRelMapper;

    @Resource
    private ILiveUserRelService liveUserRelService;


    /**
     * 直播新增
     *
     * @param model
     * @return
     */
    @Transactional
    @Override
    public boolean insert(LiveDto model) {
        boolean flag = liveBaseService.insert(model);
        if (flag) {
            //插入详情(暂时先用假数据,后面采取计算)
            LiveInfo liveInfo = new LiveInfo();
            liveInfo.setPid(model.getId());
            liveInfo.setPageViews(0);
            liveInfo.setType(1);
            liveInfoService.insert(liveInfo);
            //插入特殊人群
            List<LiveUserRel> userRelList=model.getUserRelList();
            if(userRelList.size()>0){
                userRelList.stream().forEach(item->{
                    item.setLiveId(model.getId());
                });
                liveUserRelService.insertBatch(userRelList);
            }
            return true;
        }
        return false;
    }

    /**
     * 修改
     *
     * @param model
     * @return
     */
    @Transactional
    @Override
    public boolean up(LiveDto model) {
        Boolean flag=liveBaseService.updateById(model);
        if(flag){
            //特殊人群重新绑定
            EntityWrapper<LiveUserRel> wrapper=new EntityWrapper<>();
            LiveUserRel rel=new LiveUserRel();
            rel.setLiveId(model.getId());
            wrapper.setEntity(rel);
            liveUserRelService.delete(wrapper);
            //插入特殊人群
            List userRelList=model.getUserRelList();
            if(userRelList.size()>0){
                liveUserRelService.insertBatch(userRelList);
            }
        }
        return flag;
    }

    /**
     * 直播删除
     *
     * @param id
     * @return
     */
    @Transactional
    @Override
    public boolean deleteById(Integer id) {
        HashMap infoMap = new HashMap<>();
        infoMap.put("pid", id);
        liveInfoService.deleteByMap(infoMap);
        //删除封面图文件和上传的视频
        LiveBase base = liveBaseService.selectById(id);
        String videoFileNo = base.getLiveFileNo();
        String picFileNo = base.getPicFileNo();
        LiveVideoFile videoFile=liveVideoFileService.selectById(videoFileNo);
        if(videoFile!=null){
            storageClient.deleteFile(videoFile.getFileUrl());
            liveVideoFileService.deleteById(videoFileNo);
        }
        LiveVideoFile picFile=liveVideoFileService.selectById(picFileNo);
        if(picFile!=null){
            storageClient.deleteFile(picFile.getFileUrl());
            liveVideoFileService.deleteById(picFileNo);
        }
        liveBaseService.deleteById(id);
        return true;
    }

    /**
     * 直播列表查询
     *
     * @param frontPage
     * @return
     */
    @Override
    public List<LiveVO> selectLiveList(LiveParam frontPage) {
        return liveBaseService.selectLiveList(frontPage);
    }

    @Override
    public List<LiveVO> selectLiveList(Page<LiveVO> page, LiveParam frontPage) {
        return liveBaseService.selectLiveList(page, frontPage);
    }

    /**
     * 列表导出
     *
     * @param courseParam
     * @param response
     */
    @Override
    public void exportList(LiveParam courseParam, HttpServletResponse response) {
        try {
            List<LiveVO> list = liveBaseService.selectLiveList(courseParam);
            SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
            String fileName = "直播列表" + df.format(new Date()) + ".xls";

            String[] rowsName = new String[]{"序号", "直播名", "讲师名", "直播开始时间", "直播时长", "浏览量", "积分", "直播状态"};
            List<Object[]> dataList = new ArrayList<Object[]>();
            Object[] objs = null;
            for (int i = 0; i < list.size(); i++) {
                objs = new Object[rowsName.length];
                objs[0] = i;
                objs[1] = list.get(i).getLiveName();
                objs[2] = list.get(i).getLiveTeacherName();
                objs[3] = df.format(list.get(i).getLiveTime());
                objs[4] = list.get(i).getLivePeriod();
                objs[5] = list.get(i).getPageViews();
                objs[6] = list.get(i).getIntegral();
                objs[7] = list.get(i).getLiveType();
                dataList.add(objs);
            }
            CommonExcel ex = new CommonExcel("直播导出情况", rowsName, dataList, response, fileName);
            ex.downloadExcel();
        } catch (Exception e) {
            throw new RuntimeException("直播列表导出失败");
        }
    }

    /**
     * 直播列表编辑查询
     *
     * @param id
     * @return
     */
    @Override
    public LiveVO edit(Integer id) {
        LiveVO vo = liveBaseService.selectLiveById(id);
        String liveFileNo = vo.getLiveFileNo();
        String picNo = vo.getPicFileNo();
        LiveVideoFile videoFile = liveVideoFileService.selectById(liveFileNo);
        LiveVideoFile picFile = liveVideoFileService.selectById(picNo);
        if (picFile != null) {
            vo.setPicFileNo(vo.getPicFileNo());
            vo.setPicFileName(picFile.getFileName());
        }
        if (videoFile != null) {
            vo.setVideoFileName(videoFile.getFileName());
        }
        return vo;
    }

    /**
     * 上传视频
     *
     * @param file
     * @return
     * @Param request
     */
    @Transactional
    @Override
    public ResultJson<Object> uploadVideo(MultipartFile file, HttpServletRequest request) {
        try {
            String originalFilename = file.getOriginalFilename();
            // 校验文件的类型
            String ext = StringUtils.substringAfterLast(originalFilename, ".");
            StorePath storePath = this.storageClient.uploadFile(file.getInputStream(), file.getSize(), ext, null);
            String fileUrl = storePath.getFullPath();
            if (fileUrl == null) {
                LOGGER.info("文件上传失败");
                return ResultJson.error(0, "上传文件失败");
            }
            StringBuffer fileNo = new StringBuffer();
            int filePeriod = 0;//直播时长
            if (CONTENT_TYPES.contains(ext)) {
                fileNo.append(FileUtil.getSequence(FILE_TYPE_V));
//                filePeriod = ReadVideoTime(multipartFileToFile(file));//视频流转时长有待处理
            } else {
                fileNo.append(FileUtil.getSequence(FILE_TYPE_P));
            }
            //插入文件表
            LiveVideoFile liveVideoFile = new LiveVideoFile();
            liveVideoFile.setFileName(originalFilename);
            liveVideoFile.setFileNo(fileNo.toString());
            liveVideoFile.setFileSize(formatFileSize(file.getSize()));
            liveVideoFile.setFileType(ext);
            liveVideoFile.setFileUrl(fileUrl);
            liveVideoFile.setFilePeriod(filePeriod);
            liveVideoFileService.insertOrUpdate(liveVideoFile);

            return ResultJson.ok(liveVideoFile);
        } catch (Exception e) {
            return ResultJson.error(0, "上传文件失败");
        }
    }

    /**
     * 文件删除
     *
     * @param id
     * @return
     */
    @Override
    public boolean delFile(String id) {
        LiveVideoFile file = liveVideoFileService.selectById(id);
        this.storageClient.deleteFile(file.getFileUrl());
        return liveVideoFileService.deleteById(id);
    }

    /**
     * 指定观看人群新增查询
     *
     * @return
     */
    @Override
    public List<SpecifyPersonVO> querySpecifyPerson() {
        List<SpecifyPersonVO> list=liveBaseMapper.querySpecifyPerson();
        return list.stream().filter(c->c.getId()!=null).collect(Collectors.toList());
    }

    /**
     * 指定观看人群编辑查询
     *
     * @param id
     * @return
     */
    @Override
    public List<SpecifyPersonVO> querySpecifyPerson(Integer id) {
        List<SpecifyPersonVO> list =this.querySpecifyPerson();
        EntityWrapper<LiveUserRel> wrapper = new EntityWrapper<>();
        LiveUserRel rel = new LiveUserRel();
        rel.setLiveId(id);
        wrapper.setEntity(rel);
        List<LiveUserRel> userRels = liveUserRelMapper.selectList(wrapper);
        for (SpecifyPersonVO vo : list ) {
            for (LiveUserRel item : userRels) {
                if(vo.getId().intValue() == item.getUserId().intValue()){
                    vo.setCheck(1);
                    continue;
                }
            }
        }
        return list;
    }

    /**
     * 获取视频大小
     *
     * @param source
     * @return
     */
    private int ReadVideoTime(File source) {
        Encoder encoder = new Encoder();
        try {
            MultimediaInfo m = encoder.getInfo(source);
            long ls = m.getDuration() / 1000;
            int minute = (int) ls / 60;
            return minute + 1;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0;
    }

    public static File multipartFileToFile(MultipartFile multipartFile) throws Exception {
        File file = null;
        try {
            // 获取文件名
            String fileName = multipartFile.getOriginalFilename();
            // 获取文件后缀
            String prefix = fileName.substring(fileName.lastIndexOf("."));
            // 用uuid作为文件名，防止生成的临时文件重复
            file = File.createTempFile(UUID.randomUUID().toString(), prefix);
            // MultipartFile to File
            multipartFile.transferTo(file);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return file;
    }

    /**
     * 转换文件大小
     */
    public static String formatFileSize(long fileS) {
        DecimalFormat df = new DecimalFormat("#.00");
        String fileSizeString = "";
        String wrongSize = "0B";
        if (fileS == 0) {
            return wrongSize;
        }
        if (fileS < 1024) {
            fileSizeString = df.format((double) fileS) + "B";
        } else if (fileS < 1048576) {
            fileSizeString = df.format((double) fileS / 1024) + "KB";
        } else if (fileS < 1073741824) {
            fileSizeString = df.format((double) fileS / 1048576) + "MB";
        } else {
            fileSizeString = df.format((double) fileS / 1073741824) + "GB";
        }
        return fileSizeString;
    }

}
